/**
 * @file port_ble_gatt_server.c
 * @brief 
 * @author dotc (dotchan@qq.com)
 * @date 2025-01-21
 * 
 * @copyright Copyright (c) 2025 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

#if defined(CONFIG_PORT_BLE_ENABLE)

/* ==================== [Includes] ========================================== */

// 单独控制本文件功能的优先级
#define XF_LOG_LEVEL            CONFIG_PORT_BLE_GATT_LOG_LEVEL

#include "xf_ble_gatt_server.h"
#include "xf_ble_gap.h"
#include "xf_utils.h"
#include "xf_init.h"
#include "xf_task.h"
#include "xf_ble_port_utils.h"
#include "port_ble_common.h"

#include "bledef.h"
#include "drvs.h"
#include "prf_api.h"
#include "gatt_api.h"

/* ==================== [Defines] =========================================== */

#define TAG "port_ble_gatts"

#define PORT_GATT_ATT_VAL_INFO_INDEX_INVALID    (UINT8_MAX)

/* ==================== [Typedefs] ========================================== */

/**
 * @brief svc_decl_t 的同构体，细分了成员
 */
typedef struct _port_svc_decl_t
{
    /// Service UUID (LSB First)
    union {
      uint16_t        uuid;
      uint32_t        uuid32;
      const uint8_t  *uuid128;
    };
    const att_decl_t *att_set;      /*!< 属性集合 */
    /// 
    uint16_t          att_cnt;      /*!< 属性个数，Number of attributes - extend to 16bits from v1.4 */
    /// Service information (@see enum svc_info_mask)- extend to 16bits
    struct    
    {
        uint16_t svc_hide       :1;
        uint16_t encryption     :1;
        uint16_t svc_perm_auth  :2;
        uint16_t svc_disable    :1;
        uint16_t uuid_type      :2;     // enum uuid_type, 0: 16; 1: 32; 2: 128
        uint16_t svc_type       :1;
        uint16_t svc_state_evt  :4;
        uint16_t rfu            :4;
    } info;
} port_svc_decl_t;



/**
 * Attribute information Bit Field
 *
 *   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
 * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 * |EXT | WS |IND |NTF | WR | WC | RD | B  |    NP   |    IP   |    WP   |    RP   |
 * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 *  <---------------- PROP ---------------> <---------------- PERM --------------->
 *
 * Bit [0-7]  : Attribute Permissions (@see enum sec_level)
 * Bit [8-15] : Attribute Properties
 */


/**
 * @brief att_decl_t 的同构体，细分了成员
 * 
 * @details
 * @code
 * att_decl_t 的结构信息：
 *
 *   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
 * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 * |EXT | WS |IND |NTF | WR | WC | RD | B  |    NP   |    IP   |    WP   |    RP   |
 * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 *  <---------------- PROP ---------------> <---------------- PERM --------------->
 *
 * Bit [0-7]  : Attribute Permissions (@see enum sec_level)
 * Bit [8-15] : Attribute Properties
 * 
 * @endcode
 * 
 */
typedef struct _port_att_decl_t
{
    /// Attribute UUID (LSB First)
    union {
        uint16_t        uuid;
        uint32_t        uuid32;
        const uint8_t  *uuid128;
    };
    /// Attribute information (@see enum att_info_mask)
    union {
        uint16_t        _all_u16;
        struct
        {
            
            union {
                uint8_t _all_u8:8;
                struct
                {
                    uint8_t read_sec   :2;
                    uint8_t write_sec  :2;
                    uint8_t ind_sec    :2;
                    uint8_t ntf_sec    :2;
                };
            }perm;
            uint8_t prop:8;
        };
    }src_perm;
    /// Attribute extended information (@see enum att_ext_info_mask)
    union {
        uint16_t _all_u16;
        // port_att_ext_info_mask_t info;
        struct
        {
            uint16_t val_len    :12;
            uint16_t encryption :1;
            uint16_t uuid_type  :2;     // enum uuid_type, 0: 16; 1: 32; 2: 128
            uint16_t in_present :1;
        };
        
    }src_info;

} port_att_decl_t;

/* ==================== [Static Prototypes] ================================= */

xf_err_t _default_ble_gatts_evt_cb(
    xf_ble_gatts_evt_t event,
    xf_ble_gatts_evt_cb_param_t *param);
static inline uint8_t _port_gatt_att_val_info_index_get(
    port_ble_app_t *app, uint16_t handle);
static void _port_attmdb_svc_create_cb(
    uint8_t conn_id, uint8_t opcode,
    uint16_t handle, const void *param);

/* ==================== [Static Variables] ================================== */

static xf_ble_gatts_evt_cb_t s_ble_gatts_evt_cb = _default_ble_gatts_evt_cb;

/* ==================== [Macros] ============================================ */

#define port_gatt_handle_offset(svc_start_hdl, hdl)    ((hdl) - (svc_start_hdl))

/* ==================== [Global Functions] ================================== */

/**
 * @brief BLE GATTS 服务端注册
 *
 * @param[in] app_uuid 要注册的服务端 (应用) 的 UUID ，见 @ref xf_ble_uuid_info_t
 * @param[out] app_id 服务端 (应用) ID
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_app_register(
    xf_ble_uuid_info_t *app_uuid, uint8_t *app_id)
{
    struct gapm_dev_config cfg_copy = *port_ble_dev_cfg_record_get();
    cfg_copy.gap_role |= GAP_ROLE_PERIPHERAL;

    bd_addr_t * local_addr = port_ble_get_local_addr();

    gapm_set_dev(&cfg_copy, local_addr, NULL);
    port_msg_evt_get_with_check_and_clear(PORT_MSG_EVT_BLE_SET_ROLE, 10);
   
    port_ble_dev_cfg_record_set(&cfg_copy);

    *app_id  = port_gatt_app_id_alloc();
    if(app_id == XF_BLE_GATT_APP_ID_INVALID)
    {
        return XF_ERR_RESOURCE;
    }
    return XF_OK;
}

/**
 * @brief BLE GATTS 服务端注销
 *
 * @param app_id 服务端 (应用) ID
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_app_unregister(uint8_t app_id)
{
    // struct gapm_dev_config *dev_cfg = port_ble_dev_cfg_record_get();
    /* FIXME 处理可能有多个 app 的情况*/
    // dev_cfg->gap_role &= (~GAP_ROLE_PERIPHERAL);
    
    /* TODO 暂不支持注销 */
    return XF_ERR_NOT_SUPPORTED;
}

/// Maximal length of the Device Name value
#define DEV_NAME_MAX_LEN          (20)

/**
 ****************************************************************************************
 * @brief Retrieve Dev Info to Generic Access Profile, User implement for Callback.
 *
 * @param[in]  conidx  connection index
 * @param[in]  req     iequest of info type @see enum gapc_dev_info
 * @param[in]  maxlen  buffer length, DEV_NAME_MAX_LEN or size of gapc_conn_param
 * @param[out] info    pointer of buffer
 *
 * @return Length of device information, 0 means an error occurs.
 ****************************************************************************************
 */
__weak uint16_t gap_svc_get_dev_info(uint8_t conidx, uint8_t req, uint16_t maxlen, uint8_t *info)
{
    if (req == GAPC_DEV_NAME)
    {
        uint8_t len = 0;
        xf_ble_gap_get_local_name(info, &len);
        return len;
    }
    else if (req == GAPC_DEV_APPEARANCE)
    {
        xf_ble_gap_get_local_appearance((xf_ble_appearance_t *)info);
        return sizeof(uint16_t);
    }
    #if (GAP_ATT_CFG & 0x40/*PCP_EN*/)
    else if (req == GAPC_DEV_SLV_PREF_PARAMS)
    {
        struct gapc_conn_param *slv_pref = (struct gapc_conn_param *)info;
        // Peripheral Preferred Connection Parameters
        slv_pref->intv_min = SLV_PREF_INTV_MIN;
        slv_pref->intv_max = SLV_PREF_INTV_MAX;
        slv_pref->latency  = SLV_PREF_LATENCY;
        slv_pref->time_out = SLV_PREF_TIME_OUT;
        return sizeof(struct gapc_conn_param);
    }
    #endif
    
    return 0;
}

/**
 * @brief BLE GATTS 向服务端 (应用) 添加服务
 *
 * @param app_id 服务端 (应用) ID
 * @param service 要添加的服务信息 ，见 @ref xf_ble_gatts_service_t
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_add_service_to_app(
    uint8_t app_id, xf_ble_gatts_service_t *service)
{
    XF_CHECK(service == NULL, XF_ERR_INVALID_ARG, TAG, "service == NULL");
    /* 特征声明集不为空即有效时，才创建服务添加任务 */
    XF_CHECK(service->chara_set == NULL, XF_ERR_INVALID_ARG, TAG, "service->chara_set == NULL");

    uint8_t uuid_type = PORT_BLE_UUID_TYPE_GET_FROM_XF(service->uuid->type);
    XF_LOGD(TAG, "svc uuid_type:%d %d", uuid_type, service->uuid->type);


    // // Generic Access Profile(0x1800)
    // gap_svc_init(GAP_START_HDL, GAP_ATT_CFG);
    // port_gatt_start_handle_get();
    
    // // // Generic Attribute Profile(0x1801)
    // // #if (PRF_GATT)
    // gatt_svc_init(GATT_START_HDL);
    // port_gatt_start_handle_get();
    
    uint8_t status = LE_SUCCESS;
    port_ble_app_t *app = NULL;

    uint8_t num_att_item = 0;
    uint8_t cnt_att_item = 0;
    uint8_t num_att_val = 0;

    uint8_t num_chara = 0;
    uint8_t num_desc = 0;

    /* 获取当前全局的起始句柄 */
    uint16_t hdl_start = port_gatt_start_handle_get();
    
    port_svc_decl_t svc_db = 
    {
        .uuid   = service->uuid->uuid16,  
        .info = {
            .uuid_type = uuid_type,
            .uuid_type = 0,
            .svc_perm_auth = SEC_UNAUTH,    // FIXME 暂时设置为 SEC_UNAUTH
        }
    };
    if(uuid_type == UUID_128)
    {
        svc_db.uuid128 = service->uuid->uuid128;
    }

    service->handle = port_gatt_handle_alloc(); // 申请服务的句柄

    /**
     * 2、添加服务下的特征
     * 从头检查 chara_set 数组各项，逐个特征项添加，直至遇到遇到
     * chara_uuid == XF_BLE_ATTR_SET_END_FLAG 的项结束
     */
    xf_ble_gatts_chara_t *chara_set = service->chara_set;
    
    while (chara_set[num_chara].uuid != XF_BLE_ATTR_SET_END_FLAG) {
        /**
         * 3、如果特征描述符集存在时，
         * 则从头检查 desc_set 数组各项，逐个特征项添加，直至遇到遇到
         * uuid == XF_BLE_ATTR_SET_END_FLAG 的项结束
         */
        xf_ble_gatts_chara_desc_t *desc_set = chara_set[num_chara].desc_set;
        if (desc_set == NULL) {
            ++num_chara;
            num_att_item += 2;  // 属性：特征 + 特征值
            ++num_att_val;      // 属性值：特征值
            XF_LOGD(TAG, "DESC NULL att cnt:%d,num_chara:%d", num_att_item, num_chara);
            continue;
        }
        
        num_desc = 0;
        while (desc_set[num_desc].uuid != XF_BLE_ATTR_SET_END_FLAG) {
            ++num_desc;
            ++num_att_item;     // 属性：描述符
            ++num_att_val;      // 属性值：描述符值
            XF_LOGD(TAG, "DESC att cnt:%d,num_chara:%d", num_att_item, num_chara);
        }
        ++num_chara;
        num_att_item += 2;      // 属性：特征 + 特征值
        ++num_att_val;          // 属性值：特征值
        XF_LOGD(TAG, "CHARA att cnt:%d,num_chara:%d", num_att_item, num_chara);
    }

    XF_LOGD(TAG, "att cnt:%d,num_chara:%d", num_att_item, num_chara);
    svc_db.att_cnt = num_att_item;
    
    port_att_decl_t att_decl[num_att_item];
    xf_memset(att_decl, 0, sizeof(att_decl));
    
    port_ble_gatt_att_value_t *att_val_set = xf_malloc(num_att_val * sizeof(port_ble_gatt_att_value_t));
    XF_CHECK(att_val_set == NULL, XF_ERR_NO_MEM, TAG, "att_val_set alloc failed");
    xf_memset(att_val_set, 0, num_att_val * sizeof(port_ble_gatt_att_value_t));

    /**
     * 2、添加服务下的特征
     * 从头检查 chara_set 数组各项，逐个特征项添加，直至遇到遇到
     * chara_uuid == XF_BLE_ATTR_SET_END_FLAG 的项结束
     */
    cnt_att_item = num_att_item;
    num_att_item = 0;
    num_chara = 0;
    num_att_val = 0;
    while (chara_set[num_chara].uuid != XF_BLE_ATTR_SET_END_FLAG)
    {
        XF_LOGD(TAG, "num_att_item:%d", num_att_item);
        att_decl[num_att_item] = (port_att_decl_t) {.uuid = ATT_DECL_CHARACTERISTIC, .src_perm._all_u16 = PROP_RD, .src_info = 0};

        ++num_att_item;

        /* FIXME 这里 SDK 侧定义的权限貌似不对，且找不到授权权限 */
        uint8_t prop = 
            ( (chara_set[num_chara].props >= XF_BLE_GATT_CHARA_PROP_EXTENSION)?
            XF_BLE_GATT_CHARA_PROP_EXTENSION:chara_set[num_chara].props );
        uint8_t perm = 0;
        /* SDK 中 authen 与 encrypt 位序相反*/
        uint8_t perm_enc_auth = 
                (chara_set[num_chara].perms & XF_BLE_GATT_ATTR_PERM_ENCRYPT) >> (3-2)
            |   (chara_set[num_chara].perms & XF_BLE_GATT_ATTR_PERM_AUTHEN) >> 4
        ;
    
        if(chara_set[num_chara].perms & XF_BLE_GATT_ATTR_PERM_READ)
        {
            perm |= perm_enc_auth << ATT_PERM_RP_LSB;
        }
        if(chara_set[num_chara].perms & XF_BLE_GATT_ATTR_PERM_WRITE)
        {
            perm |= perm_enc_auth << ATT_PERM_WP_LSB;
        }

        uuid_type = PORT_BLE_UUID_TYPE_GET_FROM_XF(chara_set[num_chara].uuid->type);
        att_decl[num_att_item] = (port_att_decl_t) {
            .uuid = chara_set[num_chara].uuid->uuid16,
            .src_perm.perm._all_u8 = perm,
            .src_perm.prop = prop,
            .src_info = {
                .uuid_type = uuid_type,
                .val_len = chara_set[num_chara].value_len,
            }
        };

        if(uuid_type == UUID_128)
        {
            att_decl[num_att_item].uuid128 = chara_set[num_chara].uuid->uuid128;
        }
        chara_set[num_chara].handle = port_gatt_handle_alloc();       // 申请特征的句柄
        chara_set[num_chara].value_handle = port_gatt_handle_alloc(); // 申请特征值的句柄

        att_val_set[num_att_val++] = (port_ble_gatt_att_value_t)
        {
          .hdl          = chara_set[num_chara].value_handle,
          .value        = chara_set[num_chara].value,
          .value_len    = chara_set[num_chara].value_len,
        };
        ++num_att_item;

        /**
         * 3、如果特征描述符集存在时，
         * 则从头检查 desc_set 数组各项，逐个特征项添加，直至遇到遇到
         * uuid == XF_BLE_ATTR_SET_END_FLAG 的项结束
         */
        xf_ble_gatts_chara_desc_t *desc_set = chara_set[num_chara].desc_set;
        if (desc_set == NULL) {
            ++num_chara;
            continue;
        }

        num_desc = 0;
        while (desc_set[num_desc].uuid != XF_BLE_ATTR_SET_END_FLAG) {
            uuid_type = PORT_BLE_UUID_TYPE_GET_FROM_XF(desc_set[num_desc].uuid->type);

            prop = 0;
            perm = 0;
            /* SDK 中 authen 与 encrypt 位序相反*/
            perm_enc_auth = (
                    (desc_set[num_desc].perms & XF_BLE_GATT_ATTR_PERM_ENCRYPT) >> (3-2)
                |   (desc_set[num_desc].perms & XF_BLE_GATT_ATTR_PERM_AUTHEN) >> 4
            );
        
            if(desc_set[num_desc].perms & XF_BLE_GATT_ATTR_PERM_READ)
            {
                perm |= perm_enc_auth << ATT_PERM_RP_LSB;
                prop |= XF_BLE_GATT_CHARA_PROP_READ;
            }
            if(desc_set[num_desc].perms & XF_BLE_GATT_ATTR_PERM_WRITE)
            {
                perm |= perm_enc_auth << ATT_PERM_WP_LSB;
                prop |= XF_BLE_GATT_CHARA_PROP_WRITE;
            }

            att_decl[num_att_item] = (port_att_decl_t) {
                .uuid32 = desc_set[num_desc].uuid->uuid32,
                .src_perm.perm._all_u8 = perm,
                .src_perm.prop = prop,
                .src_info = {
                    .uuid_type = uuid_type,
                    .val_len = desc_set[num_desc].value_len,
                }
            };
            if(uuid_type == UUID_128)
            {
                att_decl[num_att_item].uuid128 = desc_set[num_desc].uuid->uuid128;
            }
            desc_set[num_desc].handle = port_gatt_handle_alloc();    // 申请描述符的句柄

            att_val_set[num_att_val++] = (port_ble_gatt_att_value_t)
            {
                .hdl            = desc_set[num_desc].handle,
                .value          = desc_set[num_desc].value,
                .value_len      = desc_set[num_desc].value_len,
            };
            ++num_desc;
            ++num_att_item;
        }
        ++num_chara;
    }
    XF_LOGD(TAG, "end:hdl_start:%d,cnt_chara:%d,num_att_val:%d", hdl_start, num_chara, num_att_val);
    svc_db.att_set = (att_decl_t *)att_decl;
    
    // Create Service in database
    status = attmdb_svc_create(&hdl_start, NULL, (svc_decl_t *)&svc_db, _port_attmdb_svc_create_cb);
    XF_CHECK_GOTO(status != LE_SUCCESS, _TAG_ERR, TAG, "attmdb_svc_create error:%d", status);
    XF_LOGD(TAG, "hdl_start:%d", hdl_start);
    app = port_gatt_app_get(app_id);
    XF_ASSERT_GOTO(app != NULL, _TAG_ERR, TAG, "invalid app id:%d", app_id);

    num_att_item = 0;
    while (num_att_item < cnt_att_item)
    {
        XF_LOGD(TAG, "uuid:%#02X,src_perm:%#X,src_info:%#X", 
            att_decl[num_att_item].uuid,
            att_decl[num_att_item].src_perm._all_u16,
            att_decl[num_att_item].src_info._all_u16
        );
        ++num_att_item;
    }

    /* 有往次服务信息时，清除属性集合，回收内存 */
    if(app->p_server != NULL)
    {
        xf_free(app->p_server->att_val_set);
    }
    else
    {
        app->p_server = xf_malloc(sizeof(port_ble_gatt_server_t));
        XF_CHECK(app->p_server == NULL, XF_ERR_NO_MEM,
            TAG, "app->p_server alloc failed!");
    }

    app->p_server->att_cnt = svc_db.att_cnt;
    app->p_server->att_val_set = att_val_set;
    
    return XF_OK;

_TAG_ERR:
    xf_free(att_val_set);
    return XF_ERR_INVALID_CHECK;
}

/**
 * @brief BLE GATTS 服务开启
 *
 * @param app_id 服务端 (应用) ID
 * @param service_handle 指定的服务句柄
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_start_service(
    uint8_t app_id, uint16_t service_handle)
{
    return XF_OK;
}

/**
 * @brief BLE GATTS 服务停止
 *
 * @param app_id 服务端 (应用) ID
 * @param service_handle 指定的服务句柄
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_stop_service(
    uint8_t app_id, uint16_t service_handle)
{
    return XF_ERR_NOT_SUPPORTED;
}

/**
 * @brief BLE GATTS 删除所有服务
 *
 * @param app_id 服务端 (应用) ID
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_del_services_all(uint8_t app_id)
{
    return XF_ERR_NOT_SUPPORTED;
}

/**
 * @brief BLE GATTS 发送通知
 *
 * @param app_id 服务端 (应用) ID
 * @param conn_id 链接 (连接) ID
 * @param param 发送的通知的信息，见 @ref xf_ble_gatts_ntf_t
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_send_notification(
    uint8_t app_id, uint16_t conn_id,
    xf_ble_gatts_ntf_t *param)
{
    gatt_ntf_send(conn_id, param->handle, param->value_len, param->value);
    /* FIXME 是否需要等回调确认 */
    return XF_OK;
}

/**
 * @brief BLE GATTS 发送指示
 *
 * @param app_id 服务端 (应用) ID
 * @param conn_id 链接 (连接) ID
 * @param param 发送的指示的信息，见 @ref xf_ble_gatts_ind_t
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_send_indication(
    uint8_t app_id, uint16_t conn_id,
    xf_ble_gatts_ind_t *param)
{
    gatt_ind_send(conn_id, param->handle, param->value_len, param->value);
    /* FIXME 是否需要等回调确认 */
    return XF_OK;
}

/**
 * @brief BLE GATTS 发送 (请求的) 响应
 *
 * @param app_id 服务端 (应用) ID
 * @param conn_id 链接 (连接) ID
 * @param trans_id 传输 ID
 * @param err_code 错误码，见 @ref xf_ble_gatt_err_t
 * @param rsp 发送的响应的信息，见 @ref xf_ble_gatts_response_value_t
 * @return xf_err_t
 */
xf_err_t xf_ble_gatts_send_response(
    uint8_t app_id, uint16_t conn_id, uint32_t trans_id,
    xf_ble_gatt_err_t err_code, xf_ble_gatts_response_value_t *rsp)
{
    return XF_ERR_NOT_SUPPORTED;
}

/**
 * @brief BLE GATTS 事件回调注册
 *
 * @param evt_cb 事件回调，见 @ref xf_ble_gatts_evt_cb_t
 * @param events 事件，见 @ref xf_ble_gatts_evt_t
 * @note 当前仅支持所有事件注册在同一个回调，暂不支持指定事件对应单独的回调，
 * 所以 参数 'events' 填 0 即可
 * @return xf_err_t
 *      - XF_OK                 成功
 *      - XF_FAIL               失败
 *      - (OTHER)               @ref xf_err_t
 */
xf_err_t xf_ble_gatts_event_cb_register(
    xf_ble_gatts_evt_cb_t evt_cb,
    xf_ble_gatts_evt_t events)
{
    s_ble_gatts_evt_cb = evt_cb;
    return XF_OK;
}

xf_ble_gatts_evt_cb_t port_xf_ble_gatts_event_cb_get(void)
{
    return s_ble_gatts_evt_cb;
}

/* ==================== [Static Functions] ================================== */

/**
 * @brief 仅用于默认的事件回调函数
 *  这样可以不再在各调用处检查 s_ble_gatts_evt_cb 的有效性
 */
xf_err_t _default_ble_gatts_evt_cb(
    xf_ble_gatts_evt_t event,
    xf_ble_gatts_evt_cb_param_t *param)
{
    return XF_OK;
}

/* FIXME 待优化 */
static inline uint8_t _port_gatt_att_val_info_index_get(port_ble_app_t *app, uint16_t handle)
{
    uint8_t i = 0;
    for(; i < app->p_server->att_cnt; i++)
    {
        if(app->p_server->att_val_set[i].hdl == handle)
        {
            return i;
        }
    }
    return PORT_GATT_ATT_VAL_INFO_INDEX_INVALID;
}

static void _port_attmdb_svc_create_cb(uint8_t conn_id, uint8_t opcode, uint16_t handle, const void *param)
{
    port_ble_app_t *app = port_gatt_app_get_by_conn_id(conn_id);
    XF_CHECK(app == NULL, XF_RETURN_VOID, TAG, "app get by conn_id failed");

    /* TODO 此处没做阈值检查的，考虑是否需要 */
    uint8_t hdl_ofs = port_gatt_handle_offset(app->p_server->start_hdl, handle);

    XF_LOGD(TAG, "[ATT FUNC]:app_id:%d,conn_id:%d,op:%#x,hdl:%d,hdl_start:%d,hdl_ofs:%d",
        app->app_id, conn_id, opcode, handle, app->p_server->start_hdl, hdl_ofs);

    /* FIXME 读写请求事件时，无法区分是发现服务结构时的操作还是普通的读写操作，待解决 */
    switch (opcode)
    {
        case ATTS_READ_REQ:
        {
            XF_LOGD(TAG, ">> [ATT FUNC]:READ_REQ:hdl:%d", handle);
        
            /* 非普通读请求（发现行为）直接先自动响应服务结构中的值，再调 XF 事件回调 */
            // if(app->is_inited == false)
            {
                uint8_t index = _port_gatt_att_val_info_index_get(app, handle);
                XF_ASSERT(index != PORT_GATT_ATT_VAL_INFO_INDEX_INVALID, XF_RETURN_VOID,
                    TAG, "handle(%d) is not in app(%d)", handle, app->app_id);
                port_ble_gatt_att_value_t *val_info = &app->p_server->att_val_set[index];
                
                gatt_read_cfm(conn_id, LE_SUCCESS, handle, val_info->value_len, val_info->value);
                // return;
            }

            xf_ble_gatts_evt_cb_param_t param =
            {
                .read_req = 
                {
                    .app_id = app->app_id,
                    .conn_id = conn_id,
                    .trans_id = 0,          // FIXME 未知
                    .handle = handle,
                    .offset = 0,            // FIXME 未知
                    .need_author = 0,    // FIXME 未知
                    .need_rsp = 0,          // FIXME 未知
                    .is_long = 0,           // FIXME 未知
                }
            };
            s_ble_gatts_evt_cb(XF_BLE_GATTS_EVT_READ_REQ, &param);
        } break;
        case ATTS_WRITE_REQ:
        {
            XF_LOGD(TAG, ">> [ATT FUNC]:WRITE_REQ:hdl:%d", handle);
            const struct atts_write_ind *ind = param;

            /* 非普通写请求（发现行为）直接自动接接收到的值写入服务结构中，再调 XF 事件回调 */
            // if(app->is_inited == false)
            {
                uint8_t index = _port_gatt_att_val_info_index_get(app, handle);
                XF_ASSERT(index != PORT_GATT_ATT_VAL_INFO_INDEX_INVALID, XF_RETURN_VOID,
                    TAG, "handle(%d) is not in app(%d)", handle, app->app_id);
                port_ble_gatt_att_value_t *val_info = &app->p_server->att_val_set[index];
                
                XF_CHECK(ind->length > val_info->value_len, XF_RETURN_VOID,
                    TAG, "ind->length(%d) > value_len(%d)", ind->length, val_info->value_len);
            
                xf_memcpy(val_info->value, ind->value, ind->length);

                // Send write confirm, if no more data.
                if (ind->more == false)
                {
                    // FIXME 这里第二个参数 status 暂时直接回 LE_SUCCESS
                    gatt_write_cfm(conn_id, LE_SUCCESS, handle);

                    /* FIXME 暂时以最后一个句柄进行写请求完毕作为初始化（发现）完毕的分割线 */
                    if (app->p_server->att_cnt == (hdl_ofs-1))
                    {
                        app->p_server->is_inited = true;
                    }
                    XF_LOGD(TAG, "att_cnt:%d,hdl_ofs:%d", app->p_server->att_cnt, hdl_ofs);
                }
                
                // return;
            }

            xf_ble_gatts_evt_cb_param_t param =
            {
                .write_req = 
                {
                    .app_id = app->app_id,
                    .conn_id = conn_id,
                    .trans_id = 0,          // FIXME 未知
                    .handle = handle,
                    .offset = 0,            // FIXME 未知
                    .need_rsp = 0,          // FIXME 未知
                    .need_author = 0,    // FIXME 未知
                    .is_prep = 0,           // FIXME 未知
                    .value_len = ind->length,
                    .value = ind->value,
                }
            };

            s_ble_gatts_evt_cb(XF_BLE_GATTS_EVT_WRITE_REQ, &param);
        } break;

        case ATTS_INFO_REQ:
        {
            XF_LOGD(TAG, ">> [ATT FUNC]:INFO_REQ:hdl:%d", handle);
            
            uint8_t index = _port_gatt_att_val_info_index_get(app, handle);
            XF_ASSERT(index != PORT_GATT_ATT_VAL_INFO_INDEX_INVALID, XF_RETURN_VOID,
                TAG, "handle(%d) is not in app(%d)", handle, app->app_id);
            port_ble_gatt_att_value_t *val_info = &app->p_server->att_val_set[index];

            gatt_info_cfm(conn_id, LE_SUCCESS, handle, val_info->value_len);
        } break;

        case ATTS_CMP_EVT:
        {
            /* TODO 待做流量控制行为 */
            const struct atts_cmp_evt *evt = param;
            
            XF_LOGD(TAG, ">> [ATT FUNC]:CMP_EVT:hdl:%d,opt:%d,status:%d,seq:%d", 
                handle, evt->operation, evt->status, evt->seq_num);

            port_ble_gatt_att_value_t *att_val_set = app->p_server->att_val_set;
            uint8_t index = app->p_server->att_cnt;
            while (index--)
            {
                if(att_val_set[index].hdl == handle)
                {
                    if (evt->operation == GATT_NOTIFY)
                    {
                        // gatt_ntf_send(conn_id, handle, att_val_set[index].value_len, att_val_set[index].value);
                    }
                    else if (evt->operation == GATT_INDICATE)
                    {
                        // gatt_ind_send(conn_id, handle, att_val_set[index].value_len, att_val_set[index].value);
                    }
                    return;
                }
            }
            
            XF_LOGW(TAG, "There is no value,handle(%d)", handle);
            

            // hids_env.nb_pkt++; // release

            // DEBUG("  cmp_evt(op:0x%x,sta:0x%x,nb:%d)", evt->operation, evt->status, hids_env.nb_pkt);
            // // add 'if' to avoid warning #117-D: "evt" never referenced
            // if (evt->operation == GATT_NOTIFY)
            // {
            //     // Notify result
            // }
        } break;

        default:
        {
            // nothing to do
        } break;
    }
}

#endif
